use serde::{de::SeqAccess, Deserialize, Deserializer};

use super::Error;

struct Decoder<'a> {
    buf: &'a [u8],
    index: usize,
}

pub fn from_bytes<'a: 'de, 'de, T: Deserialize<'de>>(buf: &'a [u8]) -> Result<T, Error> {
    let mut dec = Decoder { buf, index: 0 };
    T::deserialize(&mut dec)
}

struct SeqAccess2<'a: 'b, 'b> {
    dec: &'b mut Decoder<'a>,
    len: usize,
}

impl<'a: 'b + 'de, 'b, 'de> SeqAccess<'de> for SeqAccess2<'a, 'b> {
    type Error = Error;

    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
    where
        T: serde::de::DeserializeSeed<'de>,
    {
        if self.len > 0 {
            self.len -= 1;
            let n = seed.deserialize(&mut *self.dec)?;
            Ok(Some(n))
        } else {
            Ok(None)
        }
    }

    fn size_hint(&self) -> Option<usize> {
        if self.dec.buf.len() > self.dec.index {
            Some(self.dec.buf.len() - self.dec.index)
        } else {
            None
        }
    }
}

impl<'a: 'de + 'b, 'de, 'b> Deserializer<'de> for &'b mut Decoder<'a> {
    type Error = Error;

    fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        Err(Error::INVALID)
    }

    fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        let index = self.index;
        if self.buf.len() < (index + 1) {
            return Err(Error::LENGTH);
        }
        let v = unsafe { *self.buf.get_unchecked(index) };
        self.index += 1;
        let v = match v {
            0 => false,
            1 => true,
            _ => return Err(Error::INVALID),
        };
        visitor.visit_bool(v)
    }

    fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        Err(Error::INVALID)
    }

    fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        let index = self.index;
        if self.buf.len() < (index + 1) {
            return Err(Error::LENGTH);
        }
        let n = unsafe { *self.buf.get_unchecked(index) } as usize;
        if self.buf.len() < (index + 1 + n) {
            return Err(Error::LENGTH);
        }
        let buf = &self.buf[(index + 1)..(index + 1 + n)];
        self.index += 1 + n;
        visitor.visit_borrowed_bytes(buf)
    }

    fn deserialize_char<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        Err(Error::INVALID)
    }

    fn deserialize_enum<V>(
        self,
        _name: &'static str,
        _variants: &'static [&'static str],
        _visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        Err(Error::INVALID)
    }

    fn deserialize_f32<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        Err(Error::INVALID)
    }

    fn deserialize_f64<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        Err(Error::INVALID)
    }

    fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        let index = self.index;
        if self.buf.len() < (index + 16) {
            return Err(Error::LENGTH);
        }
        self.index += 16;
        let n = unsafe {
            ((*self.buf.get_unchecked(index) as i128) << 120)
                | ((*self.buf.get_unchecked(index + 1) as i128) << 112)
                | ((*self.buf.get_unchecked(index + 2) as i128) << 104)
                | ((*self.buf.get_unchecked(index + 3) as i128) << 96)
                | ((*self.buf.get_unchecked(index + 4) as i128) << 88)
                | ((*self.buf.get_unchecked(index + 5) as i128) << 80)
                | ((*self.buf.get_unchecked(index + 6) as i128) << 72)
                | ((*self.buf.get_unchecked(index + 7) as i128) << 64)
                | ((*self.buf.get_unchecked(index + 8) as i128) << 56)
                | ((*self.buf.get_unchecked(index + 9) as i128) << 48)
                | ((*self.buf.get_unchecked(index + 10) as i128) << 40)
                | ((*self.buf.get_unchecked(index + 11) as i128) << 32)
                | ((*self.buf.get_unchecked(index + 12) as i128) << 24)
                | ((*self.buf.get_unchecked(index + 13) as i128) << 16)
                | ((*self.buf.get_unchecked(index + 14) as i128) << 8)
                | (*self.buf.get_unchecked(index + 15) as i128)
        };
        visitor.visit_i128(n)
    }

    fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        let index = self.index;
        if self.buf.len() < (index + 2) {
            return Err(Error::LENGTH);
        }
        self.index += 2;
        let n = unsafe {
            ((*self.buf.get_unchecked(index) as i16) << 8)
                | (*self.buf.get_unchecked(index + 1) as i16)
        };
        visitor.visit_i16(n)
    }

    fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        let index = self.index;
        if self.buf.len() < (index + 4) {
            return Err(Error::LENGTH);
        }
        self.index += 4;
        let n = unsafe {
            ((*self.buf.get_unchecked(index) as i32) << 24)
                | ((*self.buf.get_unchecked(index + 1) as i32) << 16)
                | ((*self.buf.get_unchecked(index + 2) as i32) << 8)
                | (*self.buf.get_unchecked(index + 3) as i32)
        };
        visitor.visit_i32(n)
    }

    fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        let index = self.index;
        if self.buf.len() < (index + 8) {
            return Err(Error::LENGTH);
        }
        self.index += 8;
        let n = unsafe {
            ((*self.buf.get_unchecked(index) as i64) << 56)
                | ((*self.buf.get_unchecked(index + 1) as i64) << 48)
                | ((*self.buf.get_unchecked(index + 2) as i64) << 40)
                | ((*self.buf.get_unchecked(index + 3) as i64) << 32)
                | ((*self.buf.get_unchecked(index + 4) as i64) << 24)
                | ((*self.buf.get_unchecked(index + 5) as i64) << 16)
                | ((*self.buf.get_unchecked(index + 6) as i64) << 8)
                | (*self.buf.get_unchecked(index + 7) as i64)
        };
        visitor.visit_i64(n)
    }

    fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        let index = self.index;
        if self.buf.len() < (index + 1) {
            return Err(Error::LENGTH);
        }
        self.index += 1;
        let n = unsafe { *self.buf.get_unchecked(index) as i8 };
        visitor.visit_i8(n)
    }

    fn deserialize_identifier<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        Err(Error::INVALID)
    }

    fn deserialize_ignored_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        Err(Error::INVALID)
    }

    fn deserialize_map<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        Err(Error::INVALID)
    }

    fn deserialize_newtype_struct<V>(
        self,
        _name: &'static str,
        _visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        Err(Error::INVALID)
    }

    fn deserialize_option<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        Err(Error::INVALID)
    }

    fn deserialize_seq<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        Err(Error::INVALID)
    }

    fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        let index = self.index;
        if self.buf.len() < (index + 1) {
            return Err(Error::LENGTH);
        }
        let n = unsafe { *self.buf.get_unchecked(index) } as usize;
        if self.buf.len() < (index + 1 + n) {
            return Err(Error::LENGTH);
        }
        let buf = &self.buf[(index + 1)..(index + 1 + n)];
        self.index += 1 + n;
        visitor.visit_borrowed_str(unsafe { core::str::from_utf8_unchecked(buf) })
    }

    fn deserialize_string<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        Err(Error::INVALID)
    }

    fn deserialize_struct<V>(
        self,
        _name: &'static str,
        fields: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        self.deserialize_tuple(fields.len(), visitor)
    }

    fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        visitor.visit_seq(SeqAccess2 { dec: self, len })
    }

    fn deserialize_tuple_struct<V>(
        self,
        _name: &'static str,
        _len: usize,
        _visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        Err(Error::INVALID)
    }

    fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        let index = self.index;
        if self.buf.len() < (index + 16) {
            return Err(Error::LENGTH);
        }
        self.index += 16;
        let n = unsafe {
            ((*self.buf.get_unchecked(index) as u128) << 120)
                | ((*self.buf.get_unchecked(index + 1) as u128) << 112)
                | ((*self.buf.get_unchecked(index + 2) as u128) << 104)
                | ((*self.buf.get_unchecked(index + 3) as u128) << 96)
                | ((*self.buf.get_unchecked(index + 4) as u128) << 88)
                | ((*self.buf.get_unchecked(index + 5) as u128) << 80)
                | ((*self.buf.get_unchecked(index + 6) as u128) << 72)
                | ((*self.buf.get_unchecked(index + 7) as u128) << 64)
                | ((*self.buf.get_unchecked(index + 8) as u128) << 56)
                | ((*self.buf.get_unchecked(index + 9) as u128) << 48)
                | ((*self.buf.get_unchecked(index + 10) as u128) << 40)
                | ((*self.buf.get_unchecked(index + 11) as u128) << 32)
                | ((*self.buf.get_unchecked(index + 12) as u128) << 24)
                | ((*self.buf.get_unchecked(index + 13) as u128) << 16)
                | ((*self.buf.get_unchecked(index + 14) as u128) << 8)
                | (*self.buf.get_unchecked(index + 15) as u128)
        };
        visitor.visit_u128(n)
    }

    fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        let index = self.index;
        if self.buf.len() < (index + 2) {
            return Err(Error::LENGTH);
        }
        self.index += 2;
        let n = unsafe {
            ((*self.buf.get_unchecked(index) as u16) << 8)
                | (*self.buf.get_unchecked(index + 1) as u16)
        };
        visitor.visit_u16(n)
    }

    fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        let index = self.index;
        if self.buf.len() < (index + 4) {
            return Err(Error::LENGTH);
        }
        self.index += 4;
        let n = unsafe {
            ((*self.buf.get_unchecked(index) as u32) << 24)
                | ((*self.buf.get_unchecked(index + 1) as u32) << 16)
                | ((*self.buf.get_unchecked(index + 2) as u32) << 8)
                | (*self.buf.get_unchecked(index + 3) as u32)
        };
        visitor.visit_u32(n)
    }

    fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        let index = self.index;
        if self.buf.len() < (index + 8) {
            return Err(Error::LENGTH);
        }
        self.index += 8;
        let n = unsafe {
            ((*self.buf.get_unchecked(index) as u64) << 56)
                | ((*self.buf.get_unchecked(index + 1) as u64) << 48)
                | ((*self.buf.get_unchecked(index + 2) as u64) << 40)
                | ((*self.buf.get_unchecked(index + 3) as u64) << 32)
                | ((*self.buf.get_unchecked(index + 4) as u64) << 24)
                | ((*self.buf.get_unchecked(index + 5) as u64) << 16)
                | ((*self.buf.get_unchecked(index + 6) as u64) << 8)
                | (*self.buf.get_unchecked(index + 7) as u64)
        };
        visitor.visit_u64(n)
    }

    fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        let index = self.index;
        if self.buf.len() < (index + 1) {
            return Err(Error::LENGTH);
        }
        self.index += 1;
        let n = unsafe { *self.buf.get_unchecked(index) };
        visitor.visit_u8(n)
    }

    fn deserialize_unit<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        Err(Error::INVALID)
    }

    fn deserialize_unit_struct<V>(
        self,
        _name: &'static str,
        _visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: serde::de::Visitor<'de>,
    {
        Err(Error::INVALID)
    }

    fn is_human_readable(&self) -> bool {
        false
    }
}
